#!/bin/sh

usage () {
	cat <<EOF>&2
${0##*/} FOLDERS DEST

Merge FOLDERS content into DEST. Existing files and folders will remain. It does
not overwrite by default. Empty folders are ignored. The resulting hierarchy is:

  DEST/FOLDER1/<folder1data>
  DEST/FOLDER2/<folder2data>
  ...

Options:
  -f: Overwrite destination.
  -r: Remove empty folders.

WARNING: Do not use over filenames with newlines.

EOF
}

OPT_OVERWRITE=false
OPT_DELEMPTY=false

while getopts ":fhr" opt; do
	case $opt in
	h)
		usage
		exit 1 ;;
	f)
		OPT_OVERWRITE=true ;;
	r)
		OPT_DELEMPTY=true ;;
	\?)
		usage
		exit 1 ;;
	esac
done

shift $((OPTIND - 1))
if [ $# -eq 0 ]; then
	usage
	exit 1
fi

## The counter is used to process all arguments but the last one. We can get the
## last argument with an 'eval'. (Safe here.)
DEST="$(eval "echo \$$#")"
count=0

for i ; do
	count=$((count+1))
	[ $count -eq $# ] && break

	while IFS= read -r FILE; do
		DESTFILE="$DEST/$FILE"
		if [ ! -e "$DESTFILE" ] || $OPT_OVERWRITE; then
			mkdir -p "$(dirname "$DESTFILE")"
			mv -v "$i/../$FILE" "$DESTFILE"

			if $OPT_DELEMPTY; then
				PARENT="$FOLDER/../$FILE"
				PARENT="${PARENT%/*}"
				rmdir "$PARENT" 2>/dev/null
			fi
		fi

		## We switch to $i so that 'find' strips the parent dirs from the path.
	done <<EOF
$(cd -- "$i/.." && find "$(basename ${i})" \( -type f -o -type l \) )
EOF
done
